package com.jason.www.disruptor;

import com.jason.www.commons.CleanEvent;
import com.jason.www.commons.FinalCleanEventSourceHandler;
import com.jason.www.pojo.EmailVo;
import com.jason.www.service.ISendEmailService;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.EventTranslatorOneArg;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import static com.jason.www.commons.DisruptorUtil.createDisruptor;

/**
 * Disruptor  并发框架异步调用
 */
@Component
public class SendEmailDisruptor implements InitializingBean, ApplicationListener<ContextClosedEvent> {
    private Disruptor<SendEmailEvent> disruptor;
    private EventTranslatorOneArg<SendEmailEvent, EmailVo> translatorOneArg;
    private RingBuffer<SendEmailEvent> ringBuffer;

    @Autowired
    ISendEmailService sendEmailService;

    public void publish(EmailVo emailVo) {
        ringBuffer.publishEvent(translatorOneArg, emailVo);
    }

    @Override
    public void afterPropertiesSet() {
        disruptor = createDisruptor(SendEmailEvent::new, 1 << 9);
        disruptor.handleEventsWith((EventHandler<SendEmailEvent>) (event, sequence, endOfBatch) -> sendEmailService.sendEmail(event.getEmailVo()))
                .then(FinalCleanEventSourceHandler.CLEAN_EVENT_HANDLER);
        disruptor.start();
        ringBuffer = disruptor.getRingBuffer();
        translatorOneArg = (event, sequence, arg0) -> event.setEmailVo(arg0);
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {

    }

    private class SendEmailEvent implements CleanEvent {
        private EmailVo emailVo;

        public EmailVo getEmailVo() {
            return emailVo;
        }

        public void setEmailVo(EmailVo emailVo) {
            this.emailVo = emailVo;
        }

        @Override
        public void clean() {
            this.emailVo = null;
        }
    }
}
